1. Source Cross Validate Functions

source("./Mean Reversion/RMR.010 Cross Validate Functions.R")

2. Load Data

pricing_data <- read_csv("./Mean Reversion/Raw Data/pricing data.csv", col_types = c("iTdddddddci")) %>% 
  filter(date_time < "2017-10-09")

3. Parameter List

Description
A list of parameters passed to the functions below that describe the mean reversion pairs trading strategy.

Arguments
time_resolution: The number of seconds that each observation spans. Takes values 300, 900, 1800, 7200, 14400, and 86400.
quote_currency: A string indicating the quote currency of the currency pairs. Takes values “USDT” or “BTC”.
cointegration_test: A string indicating whether the Engle-Granger method or distance method is used to test for cointegration. Takes values “eg” or “distance”.
adf_threshold: The threshold for the ADF test statistic. Pairs below this threshold are selected when using the Engle-Granger method.
distance_threshold: The number of coin pairs to select when using the distance method.
train_window: A lubridate period object representing the length of time the train set covers.
test_window: A lubridate period object representing the length of time the the test set covers.
model_type: A string indicating whether raw prices or log prices should be used. Takes value “raw” or “log”.
spread_type: A string indicating whether the regression uses a rolling or fixed window. Takes value “rolling” or “fixed”.
rolling_window: The number of observations used in each window of a rolling linear regression.
signal_logic: A string indicating which logic to use to generate signals. Takes values “scaled” or “discrete”.
signal_scaled_enter: The z-score threshold indicating the z-score that the signal is fully scaled in when the signal logic is scaled.
signal_discrete_enter: The z-score threshold for entering a position when the signal logic is discrete.
signal_discrete_exit: The z-score threshold for exiting a position when the signal logic is discrete.
signal_stop: A threshold for the spread z-score beyond which the strategy stops trading the coin pair.
signal_reenter: A boolean indicating whether the strategy should reenter positions after exceeding the signal_stop threshold once the spread z-score returns to a reasonable range.
signal_reenter_threshold: The z-score threshold for reentering a position if signal_reenter is TRUE. pair_allocation: A string indicating whether the capital allocation to the coin pairs should be equal or weighted. Takes values “equal”, “weighted”, and “scaled”.
pair_allocation_scaling: A double indicating the volatility scaling applied to the cointegration stat when the pair allocation is scaled.

4. Set Parameters

params <- list(time_resolution = 300, 
               quote_currency = "USDT", 
               cointegration_test = "eg", 
               adf_threshold = -3.55, 
               distance_threshold = 0.40, 
               train_window = days(25), 
               test_window = days(20), 
               model_type = "raw", 
               spread_type = "rolling", 
               rolling_window = 576, 
               signal_logic = "scaled", 
               signal_scaled_enter = 4.0, 
               signal_discrete_enter = 1.15, 
               signal_discrete_exit = 0.05, 
               signal_stop = 5.55, 
               signal_reenter = TRUE, 
               signal_reenter_threshold = 0.85, 
               pair_allocation = "equal", 
               pair_allocation_scaling = 1.25) 
number_pairs <- 8 

5. Cross Validation September 2017

plot_many(pricing_data = pricing_data,
          cutoff_date = "2017-09-01",
          params = params, 
          number_pairs = number_pairs)
## # A tibble: 8 x 3
##     coin_y    coin_x cointegration_stat
##      <chr>     <chr>              <dbl>
## 1 USDT_REP  USDT_ZEC          -5.141424
## 2 USDT_ZEC  USDT_REP          -4.809243
## 3 USDT_REP  USDT_XMR          -4.285768
## 4 USDT_ETH  USDT_LTC          -3.966150
## 5 USDT_ZEC  USDT_XMR          -3.800334
## 6 USDT_ZEC  USDT_LTC          -3.719053
## 7 USDT_ZEC  USDT_ETH          -3.579106
## 8 USDT_REP USDT_DASH          -3.554924

6. Cross Validation August 2017

plot_many(pricing_data = pricing_data,
          cutoff_date = "2017-08-01",
          params = params, 
          number_pairs = number_pairs)
## # A tibble: 15 x 3
##       coin_y    coin_x cointegration_stat
##        <chr>     <chr>              <dbl>
##  1  USDT_XMR USDT_DASH          -5.518874
##  2 USDT_DASH  USDT_XMR          -5.394223
##  3  USDT_ETH  USDT_ZEC          -5.246258
##  4  USDT_ZEC  USDT_ETH          -5.215597
##  5  USDT_REP  USDT_ZEC          -5.175159
##  6  USDT_LTC  USDT_ZEC          -4.973607
##  7  USDT_ZEC  USDT_REP          -4.832974
##  8  USDT_ZEC  USDT_LTC          -4.706494
##  9  USDT_REP  USDT_ETH          -4.500360
## 10  USDT_REP  USDT_LTC          -4.427595
## 11  USDT_LTC  USDT_REP          -4.328207
## 12  USDT_ETH  USDT_REP          -4.151579
## 13  USDT_LTC  USDT_ETH          -4.019195
## 14  USDT_ETH  USDT_LTC          -3.743634
## 15  USDT_ETH USDT_DASH          -3.694956

7. Cross Validation July 2017

plot_many(pricing_data = pricing_data,
          cutoff_date = "2017-07-01",
          params = params, 
          number_pairs = number_pairs)
## # A tibble: 8 x 3
##      coin_y   coin_x cointegration_stat
##       <chr>    <chr>              <dbl>
## 1  USDT_REP USDT_XMR          -8.970894
## 2  USDT_XMR USDT_REP          -8.755381
## 3  USDT_REP USDT_BTC          -5.526647
## 4  USDT_BTC USDT_XMR          -5.495315
## 5  USDT_XMR USDT_BTC          -5.449966
## 6  USDT_BTC USDT_REP          -5.238047
## 7 USDT_DASH USDT_LTC          -3.844027
## 8 USDT_DASH USDT_ZEC          -3.607634

8. Cross Validation June 2017

plot_many(pricing_data = pricing_data,
          cutoff_date = "2017-06-01",
          params = params, 
          number_pairs = number_pairs)
## # A tibble: 25 x 3
##       coin_y    coin_x cointegration_stat
##        <chr>     <chr>              <dbl>
##  1  USDT_REP  USDT_XMR          -8.148188
##  2  USDT_XMR  USDT_REP          -7.990751
##  3  USDT_XMR USDT_DASH          -7.536854
##  4  USDT_REP USDT_DASH          -7.533585
##  5 USDT_DASH  USDT_XMR          -7.508361
##  6 USDT_DASH  USDT_REP          -7.338676
##  7  USDT_REP  USDT_ZEC          -6.075070
##  8 USDT_DASH  USDT_ZEC          -5.898254
##  9  USDT_ZEC USDT_DASH          -5.733057
## 10  USDT_ZEC  USDT_REP          -5.662455
## # ... with 15 more rows

9. Cross Validation May 2017

plot_many(pricing_data = pricing_data,
          cutoff_date = "2017-05-01",
          params = params, 
          number_pairs = number_pairs)
## # A tibble: 17 x 3
##       coin_y    coin_x cointegration_stat
##        <chr>     <chr>              <dbl>
##  1  USDT_ZEC USDT_DASH          -5.223039
##  2 USDT_DASH  USDT_ZEC          -5.188361
##  3  USDT_REP USDT_DASH          -4.789840
##  4 USDT_DASH  USDT_REP          -4.769153
##  5  USDT_ZEC  USDT_REP          -4.628554
##  6  USDT_REP  USDT_ZEC          -4.618243
##  7  USDT_XMR  USDT_ZEC          -4.336148
##  8  USDT_ZEC  USDT_ETH          -4.294953
##  9  USDT_XMR  USDT_ETH          -4.274989
## 10 USDT_DASH  USDT_ETH          -4.169103
## 11  USDT_REP  USDT_ETH          -4.163347
## 12  USDT_ZEC  USDT_XMR          -3.976505
## 13  USDT_ETH  USDT_ZEC          -3.801298
## 14  USDT_XMR USDT_DASH          -3.734803
## 15  USDT_ETH USDT_DASH          -3.679363
## 16  USDT_ETH  USDT_REP          -3.656884
## 17  USDT_BTC  USDT_LTC          -3.611149

10. Cross Validation April 2017

plot_many(pricing_data = pricing_data,
          cutoff_date = "2017-04-01",
          params = params, 
          number_pairs = number_pairs)
## # A tibble: 8 x 3
##      coin_y    coin_x cointegration_stat
##       <chr>     <chr>              <dbl>
## 1 USDT_DASH  USDT_XMR          -4.551650
## 2  USDT_XMR USDT_DASH          -4.519761
## 3  USDT_BTC  USDT_ZEC          -4.414520
## 4  USDT_ZEC  USDT_BTC          -4.302815
## 5  USDT_ZEC  USDT_XMR          -4.014570
## 6  USDT_XMR  USDT_ZEC          -3.987019
## 7  USDT_REP  USDT_ETH          -3.804929
## 8  USDT_ETH  USDT_REP          -3.583538

11. Cross Validation March 2017

plot_many(pricing_data = pricing_data,
          cutoff_date = "2017-03-01",
          params = params, 
          number_pairs = number_pairs)
## # A tibble: 11 x 3
##       coin_y    coin_x cointegration_stat
##        <chr>     <chr>              <dbl>
##  1  USDT_LTC  USDT_ZEC          -5.133481
##  2  USDT_LTC  USDT_XMR          -5.090589
##  3  USDT_LTC  USDT_BTC          -5.072744
##  4  USDT_LTC  USDT_REP          -4.941091
##  5  USDT_LTC  USDT_ETH          -4.928465
##  6  USDT_LTC USDT_DASH          -4.924740
##  7  USDT_ETH USDT_DASH          -3.756945
##  8  USDT_XMR  USDT_REP          -3.692843
##  9 USDT_DASH  USDT_ETH          -3.688327
## 10  USDT_XMR  USDT_BTC          -3.565989
## 11  USDT_XMR  USDT_LTC          -3.550346

12. Cross Validation February 2017

plot_many(pricing_data = pricing_data,
          cutoff_date = "2017-02-01",
          params = params, 
          number_pairs = number_pairs)
## # A tibble: 16 x 3
##       coin_y    coin_x cointegration_stat
##        <chr>     <chr>              <dbl>
##  1  USDT_ETH  USDT_BTC          -5.880738
##  2  USDT_REP  USDT_ETH          -5.581765
##  3  USDT_REP  USDT_BTC          -5.551202
##  4  USDT_BTC  USDT_ETH          -5.414703
##  5  USDT_REP USDT_DASH          -5.188077
##  6  USDT_REP  USDT_LTC          -4.689989
##  7  USDT_REP  USDT_ZEC          -4.646311
##  8  USDT_REP  USDT_XMR          -4.559337
##  9  USDT_ETH USDT_DASH          -4.305797
## 10  USDT_ETH  USDT_REP          -4.065880
## 11  USDT_XMR  USDT_LTC          -3.891866
## 12  USDT_LTC  USDT_XMR          -3.839808
## 13  USDT_XMR  USDT_BTC          -3.819065
## 14  USDT_XMR  USDT_ETH          -3.753039
## 15  USDT_ZEC USDT_DASH          -3.657396
## 16 USDT_DASH  USDT_ETH          -3.566371

13. Cross Validation January 2017

plot_many(pricing_data = pricing_data,
          cutoff_date = "2017-01-01",
          params = params, 
          number_pairs = number_pairs)
## # A tibble: 9 x 3
##      coin_y    coin_x cointegration_stat
##       <chr>     <chr>              <dbl>
## 1  USDT_REP  USDT_XMR          -5.387352
## 2  USDT_REP  USDT_ETH          -4.584551
## 3  USDT_REP USDT_DASH          -4.545369
## 4  USDT_REP  USDT_BTC          -4.471198
## 5  USDT_REP  USDT_LTC          -4.455255
## 6  USDT_REP  USDT_ZEC          -4.428392
## 7  USDT_LTC  USDT_BTC          -4.139843
## 8  USDT_BTC  USDT_LTC          -3.790503
## 9 USDT_DASH  USDT_XMR          -3.564016

14. Cross Validation Full

results <- backtest_strategy_full(pricing_data = pricing_data, 
                                  params = params)  
## [1] "Cross validating strategy."
## [1] "Using train set from 2016-12-07 to 2017-01-01."
## [1] "Using test set from 2017-01-01 to 2017-01-21."
## [1] "Cross validating strategy."
## [1] "Using train set from 2016-12-27 to 2017-01-21."
## [1] "Using test set from 2017-01-21 to 2017-02-10."
## [1] "Cross validating strategy."
## [1] "Using train set from 2017-01-16 to 2017-02-10."
## [1] "Using test set from 2017-02-10 to 2017-03-02."
## [1] "Cross validating strategy."
## [1] "Using train set from 2017-02-05 to 2017-03-02."
## [1] "Using test set from 2017-03-02 to 2017-03-22."
## [1] "Cross validating strategy."
## [1] "Using train set from 2017-02-25 to 2017-03-22."
## [1] "Using test set from 2017-03-22 to 2017-04-11."
## [1] "Cross validating strategy."
## [1] "Using train set from 2017-03-17 to 2017-04-11."
## [1] "Using test set from 2017-04-11 to 2017-05-01."
## [1] "Cross validating strategy."
## [1] "Using train set from 2017-04-06 to 2017-05-01."
## [1] "Using test set from 2017-05-01 to 2017-05-21."
## [1] "Cross validating strategy."
## [1] "Using train set from 2017-04-26 to 2017-05-21."
## [1] "Using test set from 2017-05-21 to 2017-06-10."
## [1] "Cross validating strategy."
## [1] "Using train set from 2017-05-16 to 2017-06-10."
## [1] "Using test set from 2017-06-10 to 2017-06-30."
## [1] "Cross validating strategy."
## [1] "Using train set from 2017-06-05 to 2017-06-30."
## [1] "Using test set from 2017-06-30 to 2017-07-20."
## [1] "Cross validating strategy."
## [1] "Using train set from 2017-06-25 to 2017-07-20."
## [1] "Using test set from 2017-07-20 to 2017-08-09."
## [1] "Cross validating strategy."
## [1] "Using train set from 2017-07-15 to 2017-08-09."
## [1] "Using test set from 2017-08-09 to 2017-08-29."
## [1] "Cross validating strategy."
## [1] "Using train set from 2017-08-04 to 2017-08-29."
## [1] "Using test set from 2017-08-29 to 2017-09-18."
## [1] "Cross validating strategy."
## [1] "Using train set from 2017-08-24 to 2017-09-18."
## [1] "Using test set from 2017-09-18 to 2017-10-08."
ggplot(results, aes(x = date_time)) + 
  geom_line(aes(y = return_strategy_cumulative), colour = "blue", size = 1) + 
  geom_hline(yintercept = 1, colour = "black") + 
  labs(title = "Strategy Return vs Buy Hold Return", x = "Date", y = "Cumulative Return") 

print(results[["return_strategy_cumulative"]][nrow(results)]) 
## [1] 890.4977